package com.puny.mvc.helpers
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	import flexunit.framework.TestCase;

	public class HelperTest extends TestCase
	{
		private var dispatcher:EventDispatcher = new EventDispatcher();
		public function HelperTest(methodName:String=null)
		{
			super(methodName);
		}
		
		
		// procedure runs 100 times, before runs once, after runs once
		private var _process1:uint = 0;
		private var _result:uint = 0;
		public function testFrameHelper():void {
			dispatcher.addEventListener("FRAME", addAsync(done1, 10000));
			_result = 102;
			FrameHelper.setup(new Sprite(), before, procedure, after);
			
		}

		public function testFrameHelper1():void {
			dispatcher.addEventListener("FRAME", addAsync(done1, 10000));
			_result = 101;
			FrameHelper.setup(new Sprite(), null, procedure, after);
		}

		public function testFrameHelper2():void {
			dispatcher.addEventListener("FRAME", addAsync(done1, 10000));
			_result = 2;
			FrameHelper.setup(new Sprite(), before, null, after);
		}

		public function testFrameHelper3():void {
			dispatcher.addEventListener("FRAME", addAsync(done1, 10000));
			_result = 1;
			FrameHelper.setup(new Sprite(), null, null, after);
		}

		public function testFrameHelper4():void {
			_result = 101;
			var timer:Timer = new Timer(5000,1);
			timer.addEventListener(TimerEvent.TIMER, addAsync(done1,20000));
			timer.start();
			FrameHelper.setup(new Sprite(), before, procedure, null);
		}

		public function testFrameHelper5():void {
			_result = 100;
			var timer:Timer = new Timer(5000,1);
			timer.addEventListener(TimerEvent.TIMER, addAsync(done1,20000));
			timer.start();
			FrameHelper.setup(new Sprite(), null, procedure, null);
		}

		public function testFrameHelper6():void {
			_result = 1;
			var timer:Timer = new Timer(1000,1);
			timer.addEventListener(TimerEvent.TIMER, addAsync(done1,20000));
			timer.start();
			FrameHelper.setup(new Sprite(), before, null, null);
		}

		public function testFrameHelper7():void {
			_result = 0;
			var timer:Timer = new Timer(1000,1);
			timer.addEventListener(TimerEvent.TIMER, addAsync(done1,20000));
			timer.start();
			FrameHelper.setup(new Sprite(), null, null, null);
		}
		
		public function testFrameHelper8():void {
			var error:Boolean = false;
			try {
				FrameHelper.setup(null, before, procedure, after);
			} catch(e:Error) {
				assertEquals("ArgumentError: The first argument must not be null.",e);
				error = true;
			}
			assertTrue(error);
		}

		private function done1(event:Event):void {
			assertEquals(_result,_process1)
			trace("frameHelper are done");
		}
		
		private function before():void {
			_process1++;
		}
		
		private function after():void {
			_process1++;
			dispatcher.dispatchEvent(new Event("FRAME"));
		}
		
		private var _count:uint = 100;
		private function procedure():Boolean {
			_process1++;
			_count--;
			return _count > 0;
		}
		
		
		//done2 must be called after _delay milisecond.
		private var _start:Number;
		private var _delay:Number = 1000;
		public function testDelayHelper():void {
			dispatcher.addEventListener("DELAY", addAsync(done2, _delay+1000));
			_start = getTimer();
			DelayHelper.setup(_delay,null,delayHandler);
		}
		
		private function delayHandler():void {
			dispatcher.dispatchEvent(new Event("DELAY"));
		}
		
		private function done2(event:Event):void {
			assertTrue(getTimer()-_start >= _delay);
			trace("delayHelper done");
		}

		private var _helper:IHelper;
		public function testDelayHelperCancel():void {
			var timer1:Timer = new Timer(500,1);
			var timer2:Timer = new Timer(_delay+1000,1);
			timer1.addEventListener(TimerEvent.TIMER, addAsync(cancelHandler, _delay+1000));
			timer2.addEventListener(TimerEvent.TIMER, addAsync(done3CheckHandler,_delay+2000));
			dispatcher.addEventListener("DELAY", done3);
			_start = getTimer();
			_helper = DelayHelper.setup(_delay,null,delayHandler);
			timer1.start();
			timer2.start();
			assertNotNull(_helper);
		}
		
		private function cancelHandler(event:Event):void {
			assertNotNull(_helper);
			_helper.revert();
		}
		
		private var _done:Boolean = false; 
		private function done3(event:Event):void {
			_done = true;
		}

		private function done3CheckHandler(event:Event):void {
			assertFalse(_done);
			done3(null);
			assertTrue(_done);
		}
		
		public function testNullHelper():void {
			var error:Boolean = false;
			try {
				DelayHelper.setup(_delay,null,null);
			} catch(e:Error) {
				assertEquals("ArgumentError: The third argument must NOT be null.",e);
				error = true;
			}
			assertTrue(error);
		}
	}
}